﻿/*
   +----------------------------------------------------------------------+
   | TABLE EXPORT TOOL                                                    |
   +----------------------------------------------------------------------+
   | Copyright © 2013 - 2018, The Machine Studio.                         |
   +----------------------------------------------------------------------+
   | See https://gitee.com/signorinotang/ServerStudy for last version     | 
   |                                                                      |
   +----------------------------------------------------------------------+
   | Author: Downey <Email: signorinotang@sina.cn>                        |
   |                <QQ: 116297528>                                       |                                                                     |
   +----------------------------------------------------------------------+
*/


using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Data;
using System.Text;
using adc;

public interface interface_load {
    object load(adc.adc_def def, adata.zero_copy_buffer zbuf);
}

public interface interface_read_value {
    void read_value(adata.zero_copy_buffer zbuf, string[] pool, List<adc.base_type> elem_types);
}

public class N : interface_read_value {
    void interface_read_value.read_value(adata.zero_copy_buffer zbuf, string[] pool, List<adc.base_type> types)
    {

    }
}


namespace adc {
    public enum e_type {
        undefine_type,
        int_type,
        int64_type,
        float_type,
        double_type,
        string_type,
        list_type,
        map_type,
        tuple_type,
        enum_type,//枚举int
        mask_type,//掩码int
        date_type,//日期类型 格林位置时间int64
        struct_type
    };

    #region type_define

    public class base_type {
        protected e_type m_type = e_type.undefine_type;
        public e_type type { get { return m_type; } }
        public Int32 type_value { get { return (Int32)m_type; } }
        public virtual object read_value<T, R, M>(adata.zero_copy_buffer zbuf, string[] pool) where M : interface_read_value, new() { throw new Exception("Unimplemented type."); }
        public virtual void to_stream(StreamWriter s, object v) { }

        static int32_type type_i32 = new int32_type();
        static int64_type type_i64 = new int64_type();
        static float32_type type_f32 = new float32_type();
        static float64_type type_f64 = new float64_type();
        static string_type type_str = new string_type();
        static enum_type type_enum = new enum_type();
        static mask_type type_mask = new mask_type();
        static date_type type_date = new date_type();

        public static base_type read_type(adata.zero_copy_buffer zbuf)
        {
            int type = 0;
            adata.stream.read(zbuf, ref type);
            switch ((e_type)type) {
                case e_type.int_type: {
                        return type_i32;
                    }
                case e_type.int64_type: {
                        return type_i64;
                    }
                case e_type.float_type: {
                        return type_f32;
                    }
                case e_type.double_type: {
                        return type_f64;
                    }
                case e_type.string_type: {
                        return type_str;
                    }
                case e_type.enum_type: {
                        return type_enum;
                    }
                case e_type.mask_type: {
                        return type_mask;
                    }
                case e_type.date_type: {
                        return type_date;
                    }
                case e_type.list_type: {
                        var ltype = new list_type();
                        ltype.elem_type = base_type.read_type(zbuf);
                        return ltype;
                    }
                case e_type.map_type: {
                        var mtype = new map_type();
                        mtype.key_type = base_type.read_type(zbuf);
                        mtype.elem_type = base_type.read_type(zbuf);
                        return mtype;
                    }
                case e_type.tuple_type: {
                        var ttype = new tuple_type();
                        int count = 0;
                        adata.stream.read(zbuf, ref count);
                        for (int i = 0; i < count; ++i)
                            ttype.elem_types.Add(base_type.read_type(zbuf));
                        return ttype;
                    }
                case e_type.struct_type: {
                        var stype = new struct_type();
                        int count = 0;
                        adata.stream.read(zbuf, ref count);
                        for (int i = 0; i < count; ++i)
                            stype.elem_types.Add(base_type.read_type(zbuf));
                        return stype;
                    }
                default: {
                        throw new Exception("read undefined type");
                    }
            }
        }
    }
   public class int32_type : base_type {
    public int32_type()
    {
        m_type = e_type.int_type;
    }
    public override object read_value<T,R,M>(adata.zero_copy_buffer zbuf, string[] pool)
    {
        Int32 v = 0;
        adata.stream.read(zbuf, ref v);
        return v;
    }     
    public override void to_stream(StreamWriter s, object v)
    {
      s.Write(v);
    }
  }
  public class int64_type : base_type
  {
    public int64_type()
    {
      m_type = e_type.int64_type;
    }
    public override object read_value<T, R, M>(adata.zero_copy_buffer zbuf, string[] pool)
    {
      Int64 v = 0;
      adata.stream.read(zbuf, ref v);
      return v;
    }
    public override void to_stream(StreamWriter s, object v)
    {
      s.Write(v);
    }
  }
  public class float32_type : base_type
  {
    public float32_type()
    {
      m_type = e_type.float_type;
    }
    public override object read_value<T, R, M>(adata.zero_copy_buffer zbuf, string[] pool)
    {
      float v = 0;
      adata.stream.read(zbuf, ref v);
      return v;
    }
    public override void to_stream(StreamWriter s, object v)
    {
      s.Write(v);
    }
  }
  public class float64_type : base_type
  {
    public float64_type()
    {
      m_type = e_type.double_type;
    }
    public override object read_value<T, R, M>(adata.zero_copy_buffer zbuf, string[] pool)
    {
      double v = 0;
      adata.stream.read(zbuf, ref v);
      return v;
    }
    public override void to_stream(StreamWriter s, object v)
    {
      s.Write(v);
    }
  }
  public class string_type : base_type
  {
    public string_type()
    {
      m_type = e_type.string_type;
    }
    public override object read_value<T, R, M>(adata.zero_copy_buffer zbuf, string[] pool)
    {
      Int32 v = 0;
      adata.stream.read(zbuf, ref v);
      if (v <= pool.Length)
        return pool[v];
      throw new Exception("string pool overflow!");
    }
    public override void to_stream(StreamWriter s, object v)
    {
      s.Write(v);
    }
  }
  public class list_type : base_type
  {
    public base_type elem_type = null;
    public list_type()
    {
      m_type = e_type.list_type;
    }
    public override object read_value<T, R, M>(adata.zero_copy_buffer zbuf, string[] pool)
    {
        //PLAN A
        Int32 v = 0;
        adata.stream.read(zbuf, ref v);
        var vs = new List<T>();
        for (int i = 0; i < v; ++i) {
            vs.Add((T)elem_type.read_value<R, R, M>(zbuf, pool));
        }
        //PLAN B
        //Int32 v = 0;
        //adata.stream.read(zbuf, ref v);
        //var vs = new List<object>();
        //for (int i = 0; i < v; ++i)
        //{
        //    vs.Add(elem_type.read_value<R, R>(zbuf, pool));
        //}
        return vs;
    }
    public override void to_stream(StreamWriter s, object v)
    {
      var vs = (List<object>)v;
      s.Write('[');
      foreach (var val in vs)
      {
        elem_type.to_stream(s, val);
        s.Write(',');
      }
      s.Write(']');
    }
  }
  public class map_type : base_type
  {
    public base_type key_type = null;
    public base_type elem_type = null;
    public map_type()
    {
      m_type = e_type.map_type;
    }
    public override object read_value<T, R, M>(adata.zero_copy_buffer zbuf, string[] pool)
    {
      Int32 v = 0;
      adata.stream.read(zbuf, ref v);
      Dictionary<object, object> vs = new Dictionary<object, object>();
      for (int i = 0; i < v; ++i)
      {
        var pk = key_type.read_value<T, R, M>(zbuf, pool);
        var pv = elem_type.read_value<T, R, M>(zbuf, pool);
        vs.Add(pk, pv);
      }
      return vs;
    }
    public override void to_stream(StreamWriter s, object v)
    {
      var vs = (Dictionary<object, object>)v;
      s.Write('{');
      foreach (var val in vs)
      {
        key_type.to_stream(s, val.Key);
        s.Write(':');
        elem_type.to_stream(s, val.Value);
        s.Write(',');
      }
      s.Write('}');
    }
  }
  public class struct_type : base_type {
        public List<base_type> elem_types = new List<base_type>();
        public Int32 size { get { return elem_types.Count; } }
        public struct_type(){
            m_type = e_type.struct_type;
        }
        public string struct_name = null;
        public override object read_value<T, R, M>(adata.zero_copy_buffer zbuf, string[] pool)
        {
            M m = new M();
            m.read_value(zbuf, pool, elem_types);
            return m;
        }
    }

  public class tuple_type : base_type {
    public List<base_type> elem_types = new List<base_type>();

    public Int32 size { get { return elem_types.Count; } }
    public tuple_type()
    {
      m_type = e_type.tuple_type;
    }
    public override object read_value<T, R, M>(adata.zero_copy_buffer zbuf, string[] pool)
    {
      object[] vs = new object[size];
      for (int i = 0; i < size; ++i)
      {
        vs[i] = elem_types[i].read_value<T, R, M>(zbuf, pool);
      }
      return vs;
    }
    public override void to_stream(StreamWriter s, object v)
    {
      object[] vs = (object[])v;
      s.Write('[');
      for (int i = 0; i < size; ++i)
      {
        elem_types[i].to_stream(s, vs[i]);
        s.Write(',');
      }
      s.Write(']');
    }
  }
  public class enum_type : base_type
  {
    public string table_name = null;
    public enum_type()
    {
        m_type = e_type.enum_type;
    }
    public override object read_value<T, R, M>(adata.zero_copy_buffer zbuf, string[] pool)
    {
        Int32 v = 0;
        adata.stream.read(zbuf, ref v);
        return v;
    }
    public override void to_stream(StreamWriter s, object v)
    {
        s.Write(v);
    }
  }
  public class mask_type : base_type
  {
    public string table_name = null;
    public mask_type()
    {
        m_type = e_type.mask_type;
    }
    public override object read_value<T, R, M>(adata.zero_copy_buffer zbuf, string[] pool)
    {
        Int32 v = 0;
        adata.stream.read(zbuf, ref v);
        return v;
    }
    public override void to_stream(StreamWriter s, object v)
    {
        s.Write(v);
    }
  }
  public class date_type : base_type
  {
    public date_type()
    {
        m_type = e_type.date_type;
    }
    public override object read_value<T, R, M>(adata.zero_copy_buffer zbuf, string[] pool)
    {
        Int64 v = 0;
        adata.stream.read(zbuf, ref v);
        return v;
    }
    public override void to_stream(StreamWriter s, object v)
    {
        s.Write(v);
    }
  }

    #endregion

  public class field
  {
    public string name = "";
    public base_type type = null;
  };

  public class adc_def
  {
    public field[] fields = null;
    public string[] string_pool = null;
    public string name = "";
    public e_type container_type = e_type.undefine_type;
    public Int64 row_count = 0;

   
    public void Load(adata.zero_copy_buffer zbuf)
    {
      Int64 value = 0;
      adata.stream.read(zbuf, ref value);
      this.container_type = (e_type)value;
      if (zbuf.error())
      {
        throw new Exception("error read container type.");
      }
      adata.stream.read(zbuf, ref this.name);
      if (zbuf.error())
      {
        throw new Exception("error read container name.");
      }
      if (this.container_type > e_type.map_type || this.container_type < e_type.list_type)
      {
        throw new Exception("unknown container type.");
      }
      adata.stream.read(zbuf, ref value);
      if (zbuf.error())
      {
        throw new Exception("error read filed length.");
      }
      this.fields = new field[value];
      for (Int64 i = 0; i < value; ++i)
      {
        field f = new field();
        this.fields[i] = f;
        adata.stream.read(zbuf, ref f.name);
        f.type = base_type.read_type(zbuf);
        if (zbuf.error())
        {
          throw new Exception("error read filed info");
        }
      }
      adata.stream.read(zbuf, ref value);
      if (zbuf.error() || value < 0)
      {
        throw new Exception("error read string pool length");
      }
      this.string_pool = new string[value];
      for (Int64 i = 0; i < value; ++i)
      {
        adata.stream.read(zbuf, ref this.string_pool[i]);
        if (zbuf.error())
        {
          throw new Exception("error read string pool");
        }
      }
      adata.stream.read(zbuf, ref this.row_count);
      if (zbuf.error())
      {
        throw new Exception("error read row length");
      }
    }
  };

  public class obj_desc
  {
    public field[] fields = null;
    public string name = "";
    public e_type obj_type = e_type.undefine_type;
    public obj_desc(field[] fields)
    {
      this.fields = fields;
    }

    public int filed_index(string name)
    {
      for (int i = 0; i < fields.Length; ++i)
      {
        if (fields[i].name == name)
        {
          return i;
        }
      }
      return -1;
    }

  };

  public class base_obj
  {
    private obj_desc m_desc;
    private ArrayList m_values;
    private associat_container m_associats = new associat_container();

    public obj_desc Desc
    {
      set { m_desc = value; }
    }

    public base_obj(obj_desc desc)
    {
      this.m_desc = desc;
    }

    public base_obj(base_obj rhs)
    {
      this.m_desc = rhs.m_desc;
      this.m_values = rhs.m_values;
    }

    //public void load(adc.adc_def def, adata.zero_copy_buffer zbuf)
    //{
    //  m_values = new ArrayList();
    //  foreach (field f in this.m_desc.fields)
    //  {
    //    m_values.Add(f.type.read_value<T, R>(zbuf, def.string_pool));
    //  }
    //}

    public associat_container associat
    {
      get { return m_associats; }
    }

    public object this[string name]
    {
      get
      {
        for (int i = 0; i < m_desc.fields.Length; ++i)
        {
          if (m_desc.fields[i].name == name)
          {
            return m_values[i];
          }
        }
        return null;
      }
    }

    public object this[int idx]
    {
      get
      {
        if (idx < m_values.Count)
            return m_values[idx];
        //UnityEngine.Debug.LogError("cannot find " + idx);
        return null;
      }
    }
  };

  public class associat_obj
  {
    public string name = "";
    public base_obj[] m_values = null;
  }

  public class associat_container
  {
    public associat_obj[] associats = null;
    public int Count
    {
      get
      {
        if (associats == null)
          return 0;
        return associats.Length;
      }
    }

    public associat_obj this[string name]
    {
      get
      {
        if (associats != null)
        {
          for (int i = 0; i < associats.Length; ++i)
          {
            if (associats[i].name == name)
            {
              return associats[i];
            }
          }
        }
        return null;
      }
    }
  }

  //TODO:
   





  public class container { 
    public base_obj[] m_values = null;
    protected e_type m_type = e_type.undefine_type;
    protected obj_desc m_desc;
    protected container_manager m_mgr = null;
    public e_type type
    {
      get { return m_type; }
    }
    public obj_desc desc
    {
      get { return m_desc; }
    }

    public int Count
    {
      get
      {
        if (m_values == null)
          return 0;
        return m_values.Length;
      }
    }
    public int FieldCount
    {
      get { return m_desc.fields.Length; }
    }

    public virtual bool ContainsKey(int iKey)
    {
      return iKey >= 0 && iKey < m_values.Length;
    }
    public virtual bool ContainsKey(string sKey)
    {
      return false;
    }

    public void to_stream(field f, object o, StreamWriter s)
    {
      f.type.to_stream(s, o);
    }

    public virtual void to_stream(StreamWriter s)
    { }

    public virtual base_obj get_value(int index)
    {
      return null;
    }

    public virtual base_obj get_value(Int64 index)
    {
      return null;
    }

    public virtual base_obj get_value(string index)
    {
      return null;
    }

    public virtual object get_value(int index, string name)
    {
      return null;
    }

    public virtual object get_value(string index, string name)
    {
      return null;
    }

    public base_obj this[int index]
    {
      get { return get_value(index); }
    }

    public base_obj this[Int64 index]
    {
      get { return get_value(index); }
    }

    public base_obj this[string index]
    {
      get { return get_value(index); }
    }

    public virtual object this[int index, string name]
    {
        get
        {
            if (this[index] == null)
            {
                //UnityEngine.Debug.Log("Cannot find " + index);
            }
            return this[index][name];
        }
    }
    public virtual object this[string index, string name]
    {
      get { return null; }
    }
    public virtual object this[int index, int column_idx]
    {
      get { return null; }
    }
    public virtual object this[string iKey, int column_idx]
    {
      get { return null; }
    }
  };

  public class container_manager
  {
    private Dictionary<string, container> m_datas = new Dictionary<string, container>();

    static public container_manager instance = new container_manager();
    public container get(string name)
    {
        container _value;
        if(m_datas.TryGetValue(name, out _value))
        {
            return _value;
        }
        else
        {
            //UnityEngine.Debug.LogError("cannot find " + name);
            return null;
        }
    }

    public void set(string name, container con)
    {
      m_datas[name] = con;
    }

    public void process_assicat(string name)
    {
      var ass_table = m_datas[name];
      if (ass_table == null || ass_table.type != e_type.list_type)
      {
        return;
      }
      Dictionary<string, List<string[]>> ass_params = new Dictionary<string, List<string[]>>();
      for (int i = 0; i < ass_table.Count; ++i)
      {
        var ptable = (string)ass_table[i, "from"];
        var pkey = (string)ass_table[i, "from_key"];
        var ftable = (string)ass_table[i, "to"];
        var fkey = (string)ass_table[i, "to_key"];
        List<string[]> parm_list = null;
        if (ass_params.ContainsKey(ptable))
        {
          parm_list = ass_params[ptable];
        }
        else
        {
          parm_list = new List<string[]>();
          ass_params[ptable] = parm_list;
        }
        parm_list.Add(new string[3] { ftable, pkey, fkey });
      }
      foreach (var ass_param in ass_params)
      {
        var ptable = ass_param.Key;
        var param_list = ass_param.Value;
        var pt = m_datas[ptable];
        int ass_count = 0;
        foreach (var param in param_list)
        {
          var ftable = param[0];
          var pkey = param[1];
          var fkey = param[2];
          var ft = m_datas[ftable];
          var pidx = pt.desc.filed_index(pkey);
          var fidx = ft.desc.filed_index(fkey);
          foreach (var pv in pt.m_values)
          {
            List<base_obj> values = new List<base_obj>();
            if (ass_count == 0)
            {
              pv.associat.associats = new associat_obj[param_list.Count];
            }
            var ass = new associat_obj() { name = ftable };
            var k1 = pv[pidx];
            if (k1.GetType().IsArray)
            {
              object[] l1 = (object[])k1;
              foreach (var lk1 in l1)
              {
                foreach (var fv in ft.m_values)
                {
                  var k2 = fv[fidx];
                  if (lk1.Equals(k2))
                  {
                    values.Add(fv);
                  }
                }
              }
            }
            else
            {
              foreach (var fv in ft.m_values)
              {
                var k2 = fv[fidx];
                if (k1.Equals(k2))
                {
                  values.Add(fv);
                }
              }
            }
            ass.m_values = values.ToArray();
            pv.associat.associats[ass_count] = ass;
          }
          ++ass_count;
        }
      }
    }
  };

  public class list<T> : container, interface_load 
        where T : class, interface_load, new() {
    private T[] m_objects = null;

    public T[] adc_get() {
       return m_objects;
    }

    public T adc_get_value(int index) {
       if (index >= m_objects.Length || index < 0) {
          return null;
       }
       return m_objects[index];
    }

    public override base_obj get_value(int index)
    {
      if (index >= m_values.Length)
      {
        throw new Exception("access list " + this.m_desc.name + " overflow size" + index.ToString());
      }
      return m_values[index];
    }

    public override base_obj get_value(Int64 index)
    {
      if (index >= m_values.Length)
      {
        throw new Exception("access list " + this.m_desc.name + " overflow size" + index.ToString());
      }
      return m_values[index];
    }

    public override object get_value(int index, string name)
    {
      if (index >= m_values.Length)
      {
        throw new Exception("access list " + this.m_desc.name + " overflow size" + index.ToString());
      }
      return this[index][name];
    }

    public override object this[int index, string name]
    {
      get
      {
        if (index >= m_values.Length)
        {
          throw new Exception("access list " + this.m_desc.name + " overflow size" + index.ToString());
        }
        return m_values[index][name];
      }
    }

    public override object this[int index, int column_idx]
    {
      get
      {
        if (index >= m_values.Length)
        {
          throw new Exception("access list " + this.m_desc.name + " overflow size" + index.ToString());
        }
        return m_values[index][column_idx];
      }
    }

    public list(container_manager mgr = null)
    {
      m_type = e_type.list_type;
      if (mgr != null)
      {
        m_mgr = mgr;
      }
    }

    public object load(adc_def def, adata.zero_copy_buffer zbuf)
    {
      if (def.container_type != this.m_type)
      {
        throw new Exception("not a list adc data!");
      }
      obj_desc odesc = new obj_desc(def.fields);
      odesc.name = def.name;
      odesc.obj_type = def.container_type;
      this.m_desc = odesc;
      this.m_objects = new T[def.row_count];
      for (Int64 i = 0; i < def.row_count; ++i) {
          T t = new T();
          t.load(def, zbuf);
          this.m_objects[i] = t;
      }
      return 0;
    }

    public override void to_stream(StreamWriter s)
    {
      foreach (var v in m_values)
      {
        s.Write("[");
        foreach (var f in desc.fields)
        {
          to_stream(f, v[f.name], s);
          s.Write(",");
        }
        s.WriteLine("]");
      }
    }
  };

  public class map<T> : container, interface_load 
        where T: class, interface_load, new() {
    public Dictionary<object, Int32> m_KeyIndex = new Dictionary<object, Int32>();
    private T[] m_objects = null;
    
    public T adc_get_value(int iKey)
    {
        int index = 0;
        if (!m_KeyIndex.TryGetValue(iKey, out index)) {
            return null;
        }
        return m_objects[index];
    }
    public T adc_get_value(string iKey)
    {
        int index = 0;
        if (!m_KeyIndex.TryGetValue(iKey, out index)) {
            //UNITY ERROR
        }
        return m_objects[index];
    }

    public T[] adc_get()
    {
        return m_objects;
    }


    public int GetIndex(object key)
    {
      if (!m_KeyIndex.ContainsKey(key))
      {
        throw new Exception("access map " + this.m_desc.name + " hasn't key " + key.ToString());
      }
      return m_KeyIndex[key];
    }

    //public override base_obj get_value(int iKey)
    //{
    //    int index = 0;
    //    if(!m_KeyIndex.TryGetValue(iKey, out index))
    //    {
    //        //UnityEngine.Debug.LogError("cannot find key " + iKey);
    //    }
    //  return m_values[index];
    //}

    public override base_obj get_value(Int64 iKey)
    {
      int index = m_KeyIndex[iKey];
      return m_values[index];
    }

    public override base_obj get_value(string iKey)
    {
      int index = m_KeyIndex[iKey];
      return m_values[index];
    }

    public override object get_value(int iKey, string name)
    {
      int index = m_KeyIndex[iKey];
      return m_values[index][name];
    }

    public override object get_value(string iKey, string name)
    {
      int index = m_KeyIndex[iKey];
      return m_values[index][name];
    }

    public override object this[int iKey, string name]
    {
      get
      {
        int index = m_KeyIndex[iKey];
        return m_values[index][name];
      }
    }
    public override object this[string iKey, string name]
    {
      get
      {
        int index = m_KeyIndex[iKey];
        return m_values[index][name];
      }
    }
    public override object this[string iKey, int column_idx]
    {
      get
      {
        int index = m_KeyIndex[iKey];
        return m_values[index][column_idx];
      }
    }
    public override object this[int iKey, int column_idx]
    {
      get
      {
        int index = m_KeyIndex[iKey];
        return m_values[index][column_idx];
      }
    }

    public override bool ContainsKey(int iKey)
    {
      return m_KeyIndex.ContainsKey(iKey);
    }
    public override bool ContainsKey(string iKey)
    {
      return m_KeyIndex.ContainsKey(iKey);
    }
    public map(container_manager mgr = null)
    {
      m_type = e_type.map_type;
      if (mgr != null)
      {
        m_mgr = mgr;
      }
    }

    public object load(adc_def def, adata.zero_copy_buffer zbuf)
    {
        if (def.container_type != e_type.map_type) {
            throw new Exception("not a map adc data!");
        }
            obj_desc odesc = new obj_desc(def.fields);
            odesc.name = def.name;
            odesc.obj_type = def.container_type;
            this.m_desc = odesc;
            this.m_objects = new T[def.row_count];
            for (Int64 i = 0; i < def.row_count; ++i) {
                T t = new T();
                object key = t.load(def, zbuf);
                this.m_objects[i] = t;
                this.m_KeyIndex.Add(key, Convert.ToInt32(i));
            }
            return 0;
    }
        

    public override void to_stream(StreamWriter s)
    {
      foreach (var v in m_values)
      {
        s.Write("[");
        foreach (var f in desc.fields)
        {
          to_stream(f, v[f.name], s);
          s.Write(",");
        }
        s.WriteLine("]");
      }
    }
  };

    public class loader
    {
    public adata.zero_copy_buffer zbuf = null;
    public loader(){

    }

    public void load<T>(ref T value) where T : interface_load
    {
        adc_def def = new adc_def();
        def.Load(zbuf);
        value.load(def, zbuf);
    }

    public container load(adata.zero_copy_buffer zbuf, container_manager mgr)
    {
      adc_def def = new adc_def();

      def.Load(zbuf);
      container value = null;
      if (def.container_type == e_type.list_type)
      {
        //list lvalue = new list(mgr);
        //lvalue.load(def, zbuf);
        //value = lvalue;
        //mgr.set(def.name, value);
      }
      else if (def.container_type == e_type.map_type)
      {
        //map mvalue = new map(mgr);
        //mvalue.load(def, zbuf);
        //value = mvalue;
        //mgr.set(def.name, value);
      }

      return value;
    }    

    public container load(string path, container_manager mgr = null)
    {
      if (mgr == null)
      {
        mgr = container_manager.instance;
      }
      FileStream file = new FileStream(path, FileMode.Open, FileAccess.Read);
      byte[] buff = new byte[file.Length];
      file.Read(buff, 0, buff.Length);
      adata.zero_copy_buffer zbuf = new adata.zero_copy_buffer(buff);
      var ret = load(zbuf, mgr);
      file.Close();
      return ret;
    }

    public UInt64 load_pack(byte[] buff, bool commpress = false, container_manager mgr = null)
    {
        if (mgr == null)
        {
            mgr = container_manager.instance;
        }
        if (commpress == true)
        {
            //buff = SevenZip.Compression.LZMA.SevenZipHelper.Decompress(buff);
        }
        zbuf = new adata.zero_copy_buffer(buff);
        UInt64 count = 0;
        adata.stream.read(zbuf, ref count);
        //for (UInt64 i = 0; i < count; ++i)
        //{
        //    load(zbuf, mgr);
        //}
        return count;
    }

    public UInt64 load_pack(string path, bool commpress = false, container_manager mgr = null)
    {
      if (mgr == null)
      {
        mgr = container_manager.instance;
      }
      FileStream file = new FileStream(path, FileMode.Open, FileAccess.Read);
      byte[] buff = new byte[file.Length];
      file.Read(buff, 0, buff.Length);
      file.Close();
      return load_pack(buff, commpress, mgr);
    }

    public static void print(container c, StreamWriter os)
    {
      c.to_stream(os);
    }

    public static void check_zbuf(adata.zero_copy_buffer zbuf, string s)
    {
        if (zbuf.error()) {
            throw new Exception(s);
        }
    }
    }
}
